package com.novatec.dao;

import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.novatec.mvc.forms.ContratoForm;
import com.novatec.mvc.modelo.ContratoItem;
import com.novatec.mvc.modelo.DetalleContratoItem;

public class ContratosDAO {
	
	private final Logger logger = Logger.getLogger(ContratosDAO.class);
	private SimpleJdbcTemplate simpleJdbcTemplate;

	@Autowired
    public void init(DataSource dataSource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
    }

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void insertarContrato(ContratoForm contratoForm) throws ParseException {
		
		String insertContrato = "INSERT INTO contrato " +
		"(IdContrato, Modalidad, IdVendedor, FechaIni, FechaFin, FechaInicio, IdAdminCrea, FechaCreacion, IdCliente, MaxNumCajas, MaxDevoluciones, MaxAdicionalesCajas, MontoPagar, TipoPedido, TipoDevolucion, MontoGarantia, MontoGarantizar, CoberturaGarantizar, TipoGarantia, FrecuenciaCobro) " +
		"VALUES (:idContrato, :modalidad, :idVendedor, :fechaIni, :fechaFin, :fechaIni, 2, :fechaCreacion, :idCliente, 0, :maxDevoluciones, :maxAdicionalesCajas, :montoPagar, :tipoPedido, :tipoDevolucion, :montoGarantia, :montoGarantizar, :coberturaGarantizar, :tipoGarantia, :frecuenciaCobro)";
		
		String insertDetalleContrato = "INSERT INTO tipcajcontrat " +
		"(IdContrato, IdTipoCaja, PrecioCaja, IdMoneda, SaldoContable, SaldoDisponible, SaldoCliente, SaldoPorDevolver, SaldoEnLavadO) " +
		"VALUES (:idContrato, :idTipoCaja, :precioCaja, :idMoneda, :saldoContable, :saldoDisponible, 0, 0, 0)";

		contratoForm.setFechaCreacion(new Date());
		MapSqlParameterSource contratoMapSQL= new MapSqlParameterSource(new BeanMap(contratoForm));
		logger.debug(insertContrato);
		simpleJdbcTemplate.update(insertContrato, contratoMapSQL);

		for (DetalleContratoItem detalle : contratoForm.getDetalleContrato()) {
			detalle.setIdContrato(contratoForm.getIdContrato());
			MapSqlParameterSource detalleContratoMapSQL= new MapSqlParameterSource(new BeanMap(detalle));
			logger.debug(insertDetalleContrato);
			simpleJdbcTemplate.update(insertDetalleContrato, detalleContratoMapSQL);
		}
	
		logger.debug("contrato insertado");	
	}

	@SuppressWarnings("unchecked")
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void actualizarContrato(ContratoForm contratoForm) throws ParseException {
		String updateContrato = "UPDATE contrato " +
		"SET MaxAdicionalesCajas = :maxAdicionalesCajas " +
		"WHERE IdContrato = :idContrato";
		
		Map<String,Object> contratoFormMap= new BeanMap(contratoForm);
		logger.debug(updateContrato);
		simpleJdbcTemplate.update(updateContrato, contratoFormMap);
		
		logger.debug("contrato actualizado");
	}
	
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public ContratoForm getContratoById(Long idContrato) throws ParseException, DataAccessException, IllegalAccessException, InvocationTargetException {
		
		String selectContrato = "SELECT " +
		"idContrato, modalidad, idVendedor, v.login as vendedor, fechaIni, fechaFin, fechaInicio, idAdminCrea, fechaCreacion, maxNumCajas, maxDevoluciones, maxAdicionalesCajas, montoPagar, tipoPedido, tipoDevolucion, montoGarantia, montoGarantizar, coberturaGarantizar, tipoGarantia, frecuenciaCobro, " +
		"tipoPersona, ruc_dni, razonSocialNombre, direccion, zona, distrito, provincia, departamento, pais, telefono, email, gps_Latitud, gps_Longitud " +
		" FROM contrato, cliente, usuario v " +
		"WHERE contrato.idCliente = cliente.idUsuario " +
		"  AND contrato.idVendedor = v.idUsuario " +
		"  AND IdContrato = ?";
		
		logger.debug(selectContrato);
		ContratoForm contratoForm= new ContratoForm(); 
		Map<String, Object> mapContratoForm= simpleJdbcTemplate.queryForMap(selectContrato, idContrato);
		BeanUtils.populate(contratoForm, mapContratoForm);
		return contratoForm;
	}
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<DetalleContratoItem> getDetalleContratoById(Long idContrato) throws IllegalAccessException, InvocationTargetException {
		String selectDetalleContrato = "SELECT " +
		"idContrato, idTipoCaja, precioCaja, idMoneda, saldoContable, saldoDisponible, saldoCliente, saldoPorDevolver, saldoEnLavado " +
		"FROM tipcajcontrat " +
		"where IdContrato = ?";
		
		logger.debug(selectDetalleContrato);
		List<DetalleContratoItem> listaDetalleContrato = new ArrayList<DetalleContratoItem>();

		for (Map<String, Object> detalleContrato : simpleJdbcTemplate.queryForList(selectDetalleContrato, idContrato)) {
			DetalleContratoItem detalleContratoItem= new DetalleContratoItem(); 
			BeanUtils.populate(detalleContratoItem, detalleContrato);
			listaDetalleContrato.add(detalleContratoItem);
		}

		return listaDetalleContrato;
	}
	
	
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<Map<String, Object>> getContratosVigentesByIdCliente(Long idCliente) {
		String selectContrato = "SELECT " +
		"idContrato, fechaIni, fechaFin " +
		"FROM contrato " +
		"WHERE idCliente = ? " +
		"and idContEst != 3";
		

		logger.debug(selectContrato);
		
		return simpleJdbcTemplate.queryForList(selectContrato, idCliente);
	}
	
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void actualizarSaldo(Long nroorden, Integer numCajas, char accion, String tipoSaldo) {
		String updateSaldoContrato = "UPDATE tipcajcontrat tc, detsolicitud ds " +
				"set " + tipoSaldo + "=" + tipoSaldo + accion + "? " +
				"WHERE tc.idContrato = ds.idContrato and tc.idTipoCaja = ds.idTipoCaja and ds.noorden = ?";
		logger.debug("UPDATE tipcajcontrat tc, detsolicitud ds set " + tipoSaldo + "=" + tipoSaldo + accion + numCajas + " WHERE tc.idContrato = ds.idContrato and tc.idTipoCaja = ds.idTipoCaja and ds.noorden = " + nroorden);
		simpleJdbcTemplate.update(updateSaldoContrato, numCajas, nroorden);
		logger.debug("nroOrden: "+nroorden+" - saldo actualizado");	
		
	}


	//mzaldivar: Agregando lista de contratos
	
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<ContratoItem> getAllContratos() {

		RowMapper<ContratoItem> mapper = new RowMapper<ContratoItem>() {  
	        public ContratoItem mapRow(ResultSet rs, int rowNum) throws SQLException {
	        	ContratoItem contratoItem = new ContratoItem();

	        	long idcontrato = rs.getLong("c.IdContrato");
	        	String modalidad = rs.getString("c.Modalidad");
	        	String razonsocialnombre = rs.getString("cl.RazonSocialNombre");
	        	Date fechaini = rs.getDate("c.FechaIni");
	        	Date fechafin = rs.getDate("c.FechaFin");
	        	int alertavigencia = rs.getInt("AlertaVigencia");
	        	
	        	contratoItem.setIdContrato(idcontrato);
	        	contratoItem.setModalidad(modalidad);
	        	contratoItem.setNombreRazonSocial(razonsocialnombre);
	        	contratoItem.setFechaIni(fechaini);
	        	contratoItem.setFechaFin(fechafin);
	        	contratoItem.setAlertaVigencia(alertavigencia);
	        	
	            return contratoItem;
	        }
	    };

		return simpleJdbcTemplate.query("SELECT c.IdContrato,c.Modalidad,cl.RazonSocialNombre,c.FechaIni,c.FechaFin,CAST(IF(DATEDIFF(Fechafin,NOW())<=0,0,DATEDIFF(Fechafin,NOW())) AS UNSIGNED) as AlertaVigencia FROM contrato c,cliente cl WHERE c.IdCliente = cl.Idusuario", mapper);
	}

}
